
/**
 * 
 * Name = GameUnits
 * DateTime = Sat Feb 26 2022 23:10:23 GMT+0800 (中国标准时间)
 * Author = hellgeniuss
 * FileBasename = GameUnits.ts
 * FileBasenameNoExtension = GameUnits
 *
 */

import { Mino, MINO_TYPE } from "./Mino";

declare type MinoCtor = typeof Mino;


export default class GameMinoFactory {
    private static _typeMap: { [key: string]: MinoCtor } = {};

    public static initFactory() {
        this.registerType(MINO_TYPE.I, Mino_I);
        this.registerType(MINO_TYPE.O, Mino_O);
        this.registerType(MINO_TYPE.T, Mino_T);
        this.registerType(MINO_TYPE.L, Mino_L);
        this.registerType(MINO_TYPE.J, Mino_J);
        this.registerType(MINO_TYPE.S, Mino_S);
        this.registerType(MINO_TYPE.Z, Mino_Z);
    }

    public static createMino(_type: MINO_TYPE): Mino {
        const minoCtor = this.getType(_type);
        return new minoCtor();
    }

    private static getType(type: MINO_TYPE): MinoCtor {
        return this._typeMap[type + ''];
    }

    private static registerType(type: MINO_TYPE, mino: MinoCtor) {
        this._typeMap[type + ''] = mino;
    }
}

export class Mino_I extends Mino {

    get unitType(): MINO_TYPE {
        return MINO_TYPE.I;
    }

    getPos(angle: number): cc.Vec2[] {
        switch (angle) {
            case 0:
                return [
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(1, 0),
                    cc.v2(2, 0)
                ];
            case 1:
                return [
                    cc.v2(1, 1),
                    cc.v2(1, 0),
                    cc.v2(1, -1),
                    cc.v2(1, -2)
                ];
            case 2:
                return [
                    cc.v2(-1, -1),
                    cc.v2(0, -1),
                    cc.v2(1, -1),
                    cc.v2(2, -1)
                ];
            case 3:
                return [
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(0, -1),
                    cc.v2(0, -2)
                ];
        }
    }
}

export class Mino_O extends Mino {
    get unitType(): MINO_TYPE {
        return MINO_TYPE.S;
    }

    getPos(angle: number): cc.Vec2[] {
        return [
            cc.v2(0, 1),
            cc.v2(0, 0),
            cc.v2(1, 1),
            cc.v2(1, 0)
        ]
    }
}

export class Mino_T extends Mino {
    get unitType(): MINO_TYPE {
        return MINO_TYPE.T
    }

    getPos(angle: number): cc.Vec2[] {
        switch (angle) {
            case 0:
                return [
                    cc.v2(-1, 0),
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(1, 0)
                ]
            case 1:
                return [
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(0, -1),
                    cc.v2(1, 0)
                ];
            case 2:
                return [
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(1, 0),
                    cc.v2(0, -1)
                ];
            case 3:
                return [
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(0, 1),
                    cc.v2(0, -1)
                ];
        }

    }
}

export class Mino_L extends Mino {

    get unitType(): MINO_TYPE {
        return MINO_TYPE.L;
    }

    getPos(angle: number): cc.Vec2[] {
        switch (angle) {
            case 0:
                return [
                    cc.v2(-1, 1),
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(1, 0)
                ];
            case 1:
                return [
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(0, -1),
                    cc.v2(1, 1)
                ];
            case 2:
                return [
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(1, 0),
                    cc.v2(1, -1)
                ];
            case 3:
                return [
                    cc.v2(-1, -1),
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(0, -1)
                ];
        }
    }
}

export class Mino_J extends Mino {

    get unitType(): MINO_TYPE {
        return MINO_TYPE.J;
    }

    getPos(angle: number): cc.Vec2[] {
        switch (angle) {
            case 0:
                return [
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(1, 0),
                    cc.v2(1, 1)
                ];
            case 1:
                return [
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(0, -1),
                    cc.v2(1, -1)
                ]
            case 2:
                return [
                    cc.v2(-1, 0),
                    cc.v2(-1, -1),
                    cc.v2(0, 0),
                    cc.v2(1, 0)
                ];
            case 3:
                return [
                    cc.v2(-1, 1),
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(0, -1)

                ]
        }
    }
}



export class Mino_S extends Mino {
    get unitType(): MINO_TYPE {
        return MINO_TYPE.S;
    }

    getPos(angle: number): cc.Vec2[] {
        switch (angle) {
            case 0:
                return [
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(0, 1),
                    cc.v2(1, 1)
                ]
            case 1:
                return [
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(1, 0),
                    cc.v2(1, -1)
                ];
            case 2:
                return [
                    cc.v2(-1, -1),
                    cc.v2(0, -1),
                    cc.v2(0, 0),
                    cc.v2(1, 0)
                ];
            case 3:
                return [
                    cc.v2(-1, 1),
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(0, -1)
                ];
        }
    }
}

export class Mino_Z extends Mino {
    get unitType(): MINO_TYPE {
        return MINO_TYPE.Z;
    }

    getPos(angle: number): cc.Vec2[] {
        switch (angle) {
            case 0:
                return [
                    cc.v2(-1, 1),
                    cc.v2(0, 1),
                    cc.v2(0, 0),
                    cc.v2(1, 0)
                ];
            case 1:
                return [
                    cc.v2(0, -1),
                    cc.v2(0, 0),
                    cc.v2(1, 0),
                    cc.v2(1, 1)
                ];
            case 2:
                return [
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(0, -1),
                    cc.v2(1, -1)
                ];
            case 3:
                return [
                    cc.v2(-1, -1),
                    cc.v2(-1, 0),
                    cc.v2(0, 0),
                    cc.v2(0, 1)
                ]
        }
    }
}
